/**
 * This file is a part of qloudgen-sec. 
 * You can redistribute qloudgen-sec and/or modify it under the terms of the Lesser GNU General Public License version 3. 
 * qloudgen-sec is distributed WITHOUT ANY WARRANTY. 
 *
 * See the Lesser GNU General Public License for more details at http://www.gnu.org/licenses/. 
 **/
package org.qloudgen.sec.osgi.shiro;

import java.util.Hashtable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.osgi.framework.Constants;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceRegistration;

import org.qloudgen.sec.util.ExceptionUtil;
import org.qloudgen.sec.shiro.SecurityUtil;

import org.qloudgen.sec.osgi.shiro.authc.AuthenticationService;
import org.qloudgen.sec.osgi.shiro.authc.impl.AuthenticationServiceImpl;
import org.qloudgen.sec.osgi.shiro.authz.AuthorizationService;
import org.qloudgen.sec.osgi.shiro.authz.impl.AuthorizationServiceImpl;
import org.qloudgen.sec.osgi.shiro.session.SessionService;
import org.qloudgen.sec.osgi.shiro.session.impl.SessionServiceImpl;

/**
 * <p>Title: Security framework activator for OSGi</p>
 * <p>Description: Implementation security framework initialized and destroyed in osgi container.</p>
 * <p>Copyright: qloudgen/sec 2014</p>
 * @author <a href="mailto:hyq.dd.sun@gmail.com">glue.3M</a>
 */
public class SecurityActivator implements BundleActivator {
	/**
	 * Log output.
	 */
	private final static Logger logger = LoggerFactory.getLogger( SecurityActivator.class );
	/**
	 *
	 */
	private SecurityUtil security = null;
	/**
	 *
	 */
	private ServiceRegistration authenticationServiceReg = null;
	/**
	 *
	 */
	private ServiceRegistration authorizationServiceReg = null;
	/**
	 *
	 */
	private ServiceRegistration sessionServiceReg = null;
	
	/**
	 * Start current security framework.
	 *
	 * @param context
	 * @throws Exception
	 */
	@Override
	public void start(BundleContext context) throws Exception {
		//
		logger.info( "Starting security framework bundle..." );
		/**
		 * First initialized security framework.
		 */
		try {
			security = SecurityUtil.getInstance();
		}
		catch (Throwable t) {
			logger.error( "Current security framework initialized error...\n{}" , ExceptionUtil.get( t ) );
			throw new BundleException( "Current security framework initialized error..." , BundleException.ACTIVATOR_ERROR , t );
		}
		/**
		 * Register authentication service.
		 */
		authenticationServiceReg = context.registerService( AuthenticationService.class.getName() , new AuthenticationServiceImpl() , getAuthenticationProperties() );
		/**
		 * Register authorization service.
		 */
		authorizationServiceReg = context.registerService( AuthorizationService.class.getName() , new AuthorizationServiceImpl() , getAuthorizationProperties() );
		/**
		 * Register session service.
		 */
		sessionServiceReg = context.registerService( SessionService.class.getName() , new SessionServiceImpl() , getSessionProperties() );
		//
		logger.info( "Started security framework bundle..." );
	}
	
	/**
	 * Stop current security framework.
	 *
	 * @param context
	 * @throws Exception
	 */
	@Override
	public void stop(BundleContext context) throws Exception {
		//
		logger.info( "Stopping security framework bundle..." );
		/**
		 * First destroyed security framework.
		 */
		try {
			if ( security != null ) {
				security.destroy();
			}
		}
		catch (Throwable t) {
			logger.error( "Current security framework destroyed error...\n{}" , ExceptionUtil.get( t ) );
			throw new BundleException( "Current security framework destroyed error..." , BundleException.ACTIVATOR_ERROR , t );
		}
		/**
		 * Unregister authentication service.
		 */
		if ( authenticationServiceReg != null ) {
			authenticationServiceReg.unregister();
		}
		/**
		 * Unregister authorization service.
		 */
		if ( authorizationServiceReg != null ) {
			authorizationServiceReg.unregister();
		}
		/**
		 * Unregister session service.
		 */
		if ( sessionServiceReg != null ) {
			sessionServiceReg.unregister();
		}
		//
		logger.info( "Stopped security framework bundle..." );
	}
	
	/**
	 * Returns current authentication properties.
	 *
	 * @return Hashtable
	 */
	private Hashtable getAuthenticationProperties() {
		Hashtable<String, String> properties = new Hashtable<String, String>();
		properties.put( Constants.SERVICE_PID , AuthenticationService.PID );
		properties.put( Constants.SERVICE_DESCRIPTION , AuthenticationService.DESCRIPTION );
		properties.put( Constants.SERVICE_VENDOR , AuthenticationService.VENDOR );
		//
		return properties;
	}
	
	/**
	 * Returns current authorization properties.
	 *
	 * @return Hashtable
	 */
	private Hashtable getAuthorizationProperties() {
		Hashtable<String, String> properties = new Hashtable<String, String>();
		properties.put( Constants.SERVICE_PID , AuthorizationService.PID );
		properties.put( Constants.SERVICE_DESCRIPTION , AuthorizationService.DESCRIPTION );
		properties.put( Constants.SERVICE_VENDOR , AuthorizationService.VENDOR );
		//
		return properties;
	}
	
	/**
	 * Returns current session properties.
	 *
	 * @return Hashtable
	 */
	private Hashtable getSessionProperties() {
		Hashtable<String, String> properties = new Hashtable<String, String>();
		properties.put( Constants.SERVICE_PID , SessionService.PID );
		properties.put( Constants.SERVICE_DESCRIPTION , SessionService.DESCRIPTION );
		properties.put( Constants.SERVICE_VENDOR , SessionService.VENDOR );
		//
		return properties;
	}
}